home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / Speech Synthesis Manager / Documentation / The Speech Manager (text) < prev    next >
Encoding:
Text File  |  1996-05-21  |  94.4 KB  |  1,292 lines  |  [TEXT/MPS ]

  1. The Speech Manager
  2.  
  3. Speech Manager Overview   2
  4. Speech Manager Concepts   3
  5. Using the Speech Manager   4
  6. Getting Started   4
  7. Determining If the Speech Manager Is Available   4
  8. Which Version of the Speech Manager Is Running?   5
  9. Making Some Noise   5
  10. Determining If Speaking Is Complete   6
  11. A Simple Example   6
  12. Essential Calls—Simple and Useful   7
  13. Working With Voices   7
  14. Managing Connections to Speech Synthesizers   11
  15. Starting and Stopping Speech   13
  16. Using Basic Speech Controls   14
  17. Putting It All Together   17
  18. Advanced Routines   18
  19. Advanced Speech Controls   19
  20. Converting Text Into Phonemes   23
  21. Getting Information About a Speech Channel   24
  22. Advanced Control Routines   30
  23. Application-Defined Pronunciation Dictionaries   36
  24. Associating a Dictionary With a Speech Channel   37
  25. Pronunciation Dictionary Data Format   38
  26. Creating and Editing Dictionaries   39
  27. Advanced Voice Information Routines   39
  28. Embedded Speech Commands   40
  29. Embedded Speech Command Syntax   41
  30. Embedded Speech Command Set   42
  31. Embedded Speech Command Error Reporting   45
  32. Summary of Phonemes and Prosodic Controls   45
  33. Summary of the Speech Manager   49
  34. This document describes the Apple® Speech Manager, which provides a standardized method for Macintosh® applications to generate synthesized speech.
  35. The document provides an overview of the Speech Manager followed by general information about generating speech from text. The necessary information and calls needed by all text-to-speech applications are given next, followed by a simple example of speech generation. More advanced calls and special-purpose routines are described last.
  36.  
  37. Speech Manager Overview
  38.  
  39. A complete system for speech synthesis consists of the elements shown in Figure 1-1.
  40. Figure 1-1    Speech synthesis components
  41.  
  42. An application calls routines in the Speech Manager to convert character strings into speech and to adjust various parameters that affect the quality or character of the spoken output. The Speech Manager is responsible for dispatching these requests to a speech synthesizer. The speech synthesizer converts the text into sound and creates the actual audio output. 
  43. The Apple-supplied voices, pronunciation dictionaries, and speech synthesizer may reside in a single file or in separate files. These files are clearly identifiable as Speech Manager–related files and are installed and removed by being dragged into or out of the System Folder. Additional voices can be provided by bundling the resources in the resource forks of specific applications. These resources are considered private to that particular application. It is up to the individual developers to decide whether the voice resources they provide are usable on a systemwide basis or only from within their applications. 
  44. In the first release of the Speech Manager, pronunciation dictionaries are managed entirely by the application. The application is free to store dictionaries in either the resource or the data fork of a file. The application is responsible for loading the individual dictionaries into RAM and then passing a handle to the dictionary data to the Speech Manager.
  45. Applications that use the Speech Manager must provide their own human interface for selecting voices and/or controlling other speech characteristics. If voices are provided in separate files, the speech synthesizer developer is responsible for providing a method for installing these resources into the System Folder or Extensions folder. The computer must be rebooted after speech synthesizers are added to or removed from the System Folder for the desired changes to be recognized.
  46.  
  47. Speech Manager Concepts
  48.  
  49. On a simple level, speech synthesis from text input is a two-stage process. First, plain-language English text is converted into phonemic representations for the individual words. Phonemes stand for specific sounds; for a complete explanation, see “Summary of Phonemes and Prosodic Controls,” later in this document. The resulting sequence of phonemes is converted into audible sounds by mapping of the individual phonemes to a series of waveforms, which are sent to the sound hardware to be played.
  50. In reality, each stage is more complicated than this description suggests. For example, during the text-to-phoneme conversion stage, number strings, abbreviations, and special symbols must be detected and converted into appropriate words before being converted into phonemes. When a sentence such as “He earned over $2,000,000 in 1990” is spoken, it would normally be preferable to say “He earned over two million dollars in nineteen- ninety” rather than “He earned over dollar-sign, two, comma, zero, zero, zero, comma, zero, zero, zero, in one, nine, nine, zero.” To produce the desired spoken output automatically, knowledge of these sorts of constructions is built into the synthesizer.
  51. The phoneme-to-sound conversion stage is also complex. Phonemes by themselves are often not sufficient to describe the way a word should be pronounced. For example, the word “object” is pronounced differently depending on whether it is used as a noun or a verb. (When it is used as a noun, the stress is placed on the first syllable. As a verb, the stress is placed on the second syllable.) In addition to stress information, phonemes must often be augmented with pitch, duration, and other information to produce intelligible, natural-sounding speech.
  52. The speech synthesizer has many built-in rules for automatically converting text into the complex phonemic representation described above. However, there will always be words and phrases that are not pronounced the way you want. The Speech Manager allows you to provide raw phonemic information directly in order to enable very precise control over the spoken output.
  53. By default, speech synthesizers expect input in normal language text. However, using the input mode controls of the Speech Manager, you can tell the synthesizer to process input text in raw phonemic form. By using the embedded commands described in the next section, you can even mix normal language text with phonemic text within a single string or text buffer.
  54. See “Summary of Phonemes and Prosodic Controls,” later in this document, for a listing of the phonemic character set and each character’s interpretation.
  55.  
  56. Using the Speech Manager
  57.  
  58. This section describes the routines used to add speech synthesis features to an application. It is organized into three sections: “Getting Started” (Easy), “Essential Calls—Simple and Useful” (Intermediate), and “Advanced Routines.”
  59. Getting Started
  60.  
  61. If you’re just getting started with text-to-speech conversion using the Speech Manager, the following routines will get you up and running with minimal effort. If you’re developing an application that does not need to choose voices, use more than one channel of speech, or exercise real-time control over the synthesized speech, these may be the only routines you need.
  62. Determining If the Speech Manager Is Available
  63.  
  64. You can find out if the Speech Manager is available with a single call to the Gestalt Manager. 
  65. Use the Gestalt toolbox routine and the selector gestaltSpeechAttr to determine whether or not the Speech Manager is available, as shown in Listing 1-1. If Gestalt returns noErr, then the parameter argument will contain a 32-bit value indicating one or more attributes of the installed Speech Manager. If the Speech Manager exists, the bit specified by gestaltSpeechMgrPresent is set.
  66. Listing 1-1    Determining if the Speech Manager is available
  67.  
  68. Boolean SpeechAvailable (void) {
  69.     OSErr            err;
  70.     long            result;
  71.     err = Gestalt(gestaltSpeechAttr, &result);
  72.     if ((err != noErr) || !(result & 
  73.             (1 << gestaltSpeechMgrPresent)))
  74.         return FALSE;
  75.     else
  76.         return TRUE;
  77. }
  78. Which Version of the Speech Manager Is Running?
  79.  
  80. Once you have determined that the Speech Manager is installed, you can see which version of the Speech Manager is running by calling SpeechManagerVersion.
  81. SpeechManagerVersion
  82.  
  83. Returns the version of the Speech Manager installed in the system.
  84. pascal NumVersion SpeechManagerVersion (void);
  85. DESCRIPTION
  86. SpeechManagerVersion returns the version of the Speech Manager installed in the system. This call should be used to determine the compatibility of your program with the currently installed Speech Manager.
  87. RESULT CODES
  88. None
  89. Making Some Noise
  90.  
  91. The most basic operation of the Speech Manager is accomplished by using the SpeakString call. This call passes a specific text string to be spoken to the Speech Manager.
  92. SpeakString
  93.  
  94. The SpeakString function passes a specific text string to be spoken to the Speech Manager.
  95. pascal OSErr SpeakString (StringPtr myString);
  96. Field descriptions
  97. myString    Text string to be spoken
  98. DESCRIPTION
  99. SpeakString attempts to speak the Pascal-style text string contained in myString. Speech is produced asynchronously using the default system voice. When an application calls this function, the Speech Manager makes a copy of the passed string and creates any structures required to speak it. As soon as speaking has begun, control is returned to the application. The synthesized speech is generated transparently to the application so that normal processing can continue while the text is being spoken. No further interaction with the Speech Manager is required at this point, and the application is free to release or purge or trash the original string.
  100. If SpeakString is called while a prior string is still being spoken, the audio currently being synthesized is interrupted immediately. Conversion of the new text into speech is then initiated. If an empty (zero length) string or a null string pointer is passed to SpeakString, it stops the synthesis of any prior string but does not generate any additional speech.
  101. As with all Speech Manager routines that expect text arguments, the text may contain embedded speech control commands. 
  102. Result CodesnoErr    0    No error    
  103. memFullErr    –108    Not enough memory to speak    
  104. synthOpenFailed    –241    Could not open another speech synthesizer channel    
  105.  
  106. Determining If Speaking Is Complete
  107.  
  108. Once an application starts a speech process with SpeakString, the next thing it will probably need to know is whether the string has been completely spoken. It can use SpeechBusy to determine whether or not the system is still speaking.
  109. SpeechBusy
  110.  
  111. The SpeechBusy routine is useful when you want to ensure that an earlier speech request has been completed before having the system speak again.
  112. pascal short SpeechBusy (void);
  113. DESCRIPTION
  114. SpeechBusy returns the number of channels of speech that are currently synthesizing speech in the application. If you use just SpeakString to initiate speech, SpeechBusy will always return 1 as long as speech is being produced. When SpeechBusy returns 0, all initiated speech has finished. 
  115. RESULT CODES
  116. None
  117. A Simple Example
  118.  
  119. The example shown in Listing 1-2 demonstrates how to use the routines introduced in this section. It first makes sure the Speech Manager is available. Then it starts speaking a string (hard-coded in this example, but more commonly loaded from a resource) and loops, doing some screen drawing, until the string is completely spoken. This example uses the SpeechAvailable routine shown in Listing 1-1.
  120. Listing 1-2    Elementary Speech Manager calls
  121.  
  122. OSErr err;
  123. if (SpeechAvailable()) {
  124.     err = SpeakString("\pThe cat sat on the mat.");
  125.     if (err == noErr)
  126.         while (SpeechBusy() > 0)
  127.             CoolAnimationRoutine();
  128.     else
  129.         NotSoCoolAlertRoutine(err);
  130. }
  131. Essential Calls—Simple and Useful
  132.  
  133. While the routines presented in the last section are simple to use, their applicability is limited to a few basic speech scenarios. This section describes additional routines that let you work with different voices and adjust some basic characteristics of the synthesized speech.
  134. Working With Voices
  135.  
  136. When describing a person’s voice, we talk about the particular set of characteristics that help us to distinguish that person’s voice from another. For example, the rate at which one speaks (slow or fast) and the average pitch (high or low) characterize a particular speaker on a crude level. In the context of the Speech Manager, a voice is the set of parameters that specify a particular quality of synthesized speech. This portion of the Speech Manager is used to determine which voices are available and to select particular voices.
  137. Every specific voice has a unique ID associated with it, which is the primary way an application refers to it. Within the Speech Manager a unique voice ID is called a VoiceSpec structure.
  138. The Speech Manager provides two routines to count and step through the list of currently available voices. CountVoices is used to compute how many voices are available with the current system. GetIndVoice uses an index, starting at 1, to return information about all currently installed voices.
  139. Use the GetIndVoice routine to step through the list of available voices. It will fill a VoiceSpec record that can be used to obtain descriptive information about the voice or to speak using that voice.
  140. Any application that wishes to use multiple voices will probably need additional information about the available voices beyond the VoiceSpec structure, such as the name of the voice and perhaps what script and language each voice supports. This information might be presented to the user in a “voice picker” dialog box or voice menu, or it might be used internally by an application trying to find a voice that meets certain criteria. Applications can use the GetVoiceDescription routine for these purposes.
  141. MakeVoiceSpec
  142.  
  143. To maximize compatibility with future versions of the Speech Manager, you should always use MakeVoiceSpec instead of setting the fields of the VoiceSpec structure directly.
  144. pascal OSErr MakeVoiceSpec (OSType creator, OSType id, VoiceSpec *voice);
  145. typedef struct VoiceSpec {
  146.     OSType            creator;         // determines which synthesizer is required 
  147.     OSType            id;             // voice ID on the specified synth 
  148. } VoiceSpec;
  149. Field descriptions
  150. creator    The synthesizer required by your application
  151. id    Identification number for this voice
  152. *voice    Pointer to the VoiceSpec structure
  153. DESCRIPTION
  154. Most voice management routines expect to be passed a pointer to a VoiceSpec structure. MakeVoiceSpec is a utility routine provided to facilitate the creation of VoiceSpec records. On return, the passed VoiceSpec structure contains the appropriate values.
  155. Voices are stored in resources of type 'ttsv' in the resource fork of Macintosh files. The Speech Manager uses the same search method as the Resource Manager, looking for voice resources in three different locations when attempting to resolve VoiceSpec references. It first looks in the application’s resource file chain. If the specified voice is not found in an open file, it then looks in the System Folder and the Extensions folder (or in just the System Folder under System 6) for files of type 'ttsv' (single-voice files) or 'ttsb' (multivoice files) and in text-to-speech synthesizer component files (file type 'INIT' or 'thng'). Voices stored in the System Folder or Extensions folder are normally available to all applications. Voices stored in the resource fork of an application files are private to the application.
  156. RESULT CODEnoErr    0    No error    
  157.  
  158. While the determination of specific voice ID values is mostly left to synthesizer developers, the voice creator values are specified by Apple (they would ordinarily correspond to a developer’s currently assigned creator ID). For both the creator and id fields Apple further reserves the set of OSType values specified entirely by space characters and lowercase letters. Apple is establishing a standard suite of voice ID values that developers can count upon being available with all speech synthesizers.
  159. CountVoices
  160.  
  161. The CountVoices routine returns the number of voices available.
  162. pascal OSErr CountVoices (short *voiceCount);
  163. Field descriptions
  164. voiceCount    Number of voices available to the application
  165. DESCRIPTION
  166. Each time CountVoices is called, the Speech Manager searches for new voices. This algorithm supports dynamic installation of voices by applications or users. On return, the voiceCount parameter contains the number of voices available.
  167. RESULT CODESnoErr    0    No error    
  168.  
  169. GetIndVoice
  170.  
  171. The GetIndVoice routine returns information about a specific voice.
  172. pascal OSErr GetIndVoice (short index, VoiceSpec *voice);
  173. Field descriptions
  174. index    Index value for a specific voice
  175. *voice    Pointer to the VoiceSpec structure
  176. DESCRIPTION
  177. As with all other index-based routines in the Macintosh Toolbox, an index value of 1 causes GetIndVoice to return information for the first voice. The order that voices are returned is not presently defined and should not be assumed. Speech Manager behavior when voice files or resources are added, removed, or modified is also presently undefined. However, calling CountVoices or GetIndVoice with an index of 1 will force the Speech Manager to update its list of available voices. GetIndVoice will return a voiceNotFound error if the passed index value exceeds the number of available voices.
  178. RESULT CODESnoErr    0    No error    
  179. voiceNotFound    –244    Voice resource not found    
  180.  
  181. GetVoiceDescription
  182.  
  183. The GetVoiceDescription routine returns information about a voice beyond that provided by GetIndVoice.
  184. pascal OSErr GetVoiceDescription (VoiceSpec *voice,
  185.             VoiceDescription *info, long infoLength);
  186. enum {kNeuter = 0, kMale, kFemale};    // returned in gender field below 
  187.  
  188. typedef struct VoiceDescription {
  189.     long                length;                    // size of structure 
  190.     VoiceSpec                voice;                    // synth and ID info for voice 
  191.     long                version;                    // version code for voice 
  192.     Str63                name;                    // name of voice 
  193.     Str255                comment;                    // additional text info about voice 
  194.     short                gender;                    // neuter, male, or female 
  195.     short                age;                    // approximate age in years 
  196.     short                script;                    // script code of text voice can process 
  197.     short                language;                    // language code of voice output speech 
  198.     short                region;                    // region code of voice output speech 
  199.     long                reserved[4];                    // always zero - reserved 
  200. } VoiceDescription;
  201. Field descriptions
  202. *voice    Pointer to the VoiceSpec structure
  203. *info    Pointer to structure containing parameters for the specified voice
  204. infoLength    Length in bytes of info structure
  205. DESCRIPTION
  206. The Speech Manager fills out the passed VoiceDescription fields with the correct information for the specified voice. If a null VoiceSpec pointer is passed, the Speech Manager returns information for the system default voice. If the VoiceDescription pointer is null, the Speech Manager simply verifies that the specified VoiceSpec refers to an available voice. If VoiceSpec does not refer to a known voice, GetVoiceDescription returns a voiceNotFound error, as shown in Listing 1-3.
  207. To maximize compatibility with future versions of the Speech Manager, the application must pass the size of the VoiceDescription structure. Having the application do this ensures that the Speech Manager will never write more data into the passed structure than will fit even if additional information fields are defined in the future. On returning from GetVoiceDescription, the length field is set to reflect the length of data actually written by this routine.
  208. Listing 1-3    Getting information about a voice
  209.  
  210. OSErr GetVoiceGender (VoiceSpec *voicePtr, short *gender) {
  211.     OSErr                err;
  212.     VoiceDescription        vd;
  213.     err = GetVoiceDescription
  214.         (voicePtr,&vd,sizeof(VoiceDescription));
  215.     if (err == noErr) {
  216.         if (vd.length > offsetof(VoiceDescription,gender))
  217.             *gender = vd.gender;
  218.         else
  219.             err = badStructLen;
  220.     }
  221.     return err;
  222. }
  223. RESULT CODESnoErr    0    No error    
  224. paramErr    –50    Parameter error    
  225. memFullErr    –108    Not enough memory to load voice into memory    
  226. voiceNotFound    –244    Voice resource not found    
  227.  
  228. Managing Connections to Speech Synthesizers
  229.  
  230. Using the routines described earlier in this document, an application can select the voice with which to speak. The next step is to associate the selected voice with the proper speech synthesizer. This is accomplished by creating a new speech channel with the NewSpeechChannel routine. A speech channel is a private communication connection to the speech synthesizer, much as a file reference number is a communication channel to an open file in the Macintosh file system.
  231. The DisposeSpeechChannel routine closes a speech channel when the application is finished with it and releases any resources that have been allocated to support the speech synthesizer and are no longer needed.
  232. NewSpeechChannel
  233.  
  234. The NewSpeechChannel routine creates a new speech channel.
  235. pascal OSErr NewSpeechChannel (VoiceSpec *voice, 
  236.     SpeechChannel *chan);
  237. Field descriptions
  238. *voice    Pointer to the VoiceSpec structure
  239. *chan    Pointer to the new channel
  240. DESCRIPTION
  241. The Speech Manager automatically locates and opens a connection to the proper synthesizer for a specified voice and sets up a channel at the location pointed to by *chan so that it is ready to speak with that voice. If a null VoiceSpec pointer is passed to NewSpeechChannel, the Speech Manager uses the current system default voice.
  242. There is no predefined limit to the number of speech channels an application may create. However, system constraints on available RAM, processor loading, and number of available sound channels may limit the number of speech channels actually possible.
  243. RESULT CODESnoErr    0    No error    
  244. memFullErr    –108    Not enough memory to open speech channel    
  245. synthOpenFailed    –241    Could not open another speech synthesizer channel    
  246. voiceNotFound    –244    Voice resource not found    
  247.  
  248. DisposeSpeechChannel
  249.  
  250. The DisposeSpeechChannel routine disposes of an existing speech channel.
  251. pascal OSErr DisposeSpeechChannel (SpeechChannel chan);
  252. Field descriptions
  253. chan    Specific speech channel
  254. DESCRIPTION
  255. This routine disposes of an existing speech channel. Any speech channels that have not been explicitly disposed of by the application are released automatically by the Speech Manager when the application quits.
  256. RESULT CODESnoErr    0    No error    
  257. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  258.  
  259. Starting and Stopping Speech
  260.  
  261. All the remaining routines in this section require a valid speech channel to work properly. Once the application has successfully created a speech channel, it can start to speak. You use the SpeakText routine to begin speaking on a speech channel.
  262. At any time during the speaking process, the application can stop the synthesizer’s speech. The StopSpeech routine will immediately abort any speech being produced on the specified speech channel and force the channel back into an idle state.
  263. SpeakText
  264.  
  265. The SpeakText routine converts a designated text into speech.
  266. pascal OSErr SpeakText (SpeechChannel chan, Ptr textBuf, long
  267.     byteLength);
  268. Field descriptions
  269. chan    Specific speech channel
  270. textBuf    Buffer of text
  271. byteLength    Length of textBuf
  272. DESCRIPTION
  273. In addition to a valid speech channel, SpeakText expects a pointer to the text to be spoken and the length in bytes of the text buffer. SpeakText will convert the given text stream into speech using the voice and control settings for that speech channel. The speech is generated asynchronously. This means that control is returned to your application before the speech has finished (probably even before it has begun). The maximum length of text buffer that can be spoken is limited only by the available RAM. However, it’s generally not very friendly to force the user to listen to long uninterrupted text unless the user requests it. 
  274. If SpeakText is called while it is currently busy speaking the contents of a prior text buffer, it will immediately stop speaking from the prior buffer and will begin speaking from the new text buffer as soon as possible. As with SpeakString, described on page 5, if an empty (zero length) string or a null text buffer pointer is passed to SpeakText, this will have the effect of stopping the synthesis of any prior text but will not generate any additional speech.
  275. sWARNING
  276. With SpeakText, unlike with SpeakString, the text buffer must be locked in memory and must not move during the entire time that it is being converted into speech. This buffer is read at interrupt time, and very undesirable effects will happen if it moves or is purged from memory.s
  277. RESULT CODESnoErr    0    No error    
  278. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  279.  
  280. StopSpeech
  281.  
  282. The StopSpeech routine terminates speech delivery on a specified channel.
  283. pascal OSErr StopSpeech (SpeechChannel chan);
  284. Field descriptions
  285. chan    Specific speech channel
  286. DESCRIPTION
  287. After returning from StopSpeech, the application can safely release any text buffer that that the speech synthesizer has been using. The SpeechBusy routine, described on page 6, can be used to determine if the text has been completely spoken. (In an environment with multiple speech channels, you may need to use the more advanced status routine GetSpeechInfo, described on page 25, to determine if a specific channel is still speaking.) StopSpeech can be called for an already idle channel without ill effect. 
  288. RESULT CODESnoErr    0    No error    
  289. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  290.  
  291. Using Basic Speech Controls
  292.  
  293. The Speech Manager provides several methods of adjusting the variables that can affect the way speech is synthesized. Although most applications probably do not need to use these advanced features, two of the speech variables, speaking rate and speaking pitch, are useful enough that a very simple way of adjusting these parameters on a channel-by-channel basis is provided. Routines are supplied that enable an application to both set and get these parameters. However, the audible effects of changing the rate and pitch of speech vary from synthesizer to synthesizer; you should test the actual results on all synthesizers with which your application may work.
  294. Speaking rates are specified in terms of words per minute (WPM). While this unit of measurement is difficult to define in any precise way, it is generally easy to understand and use. The range of supported rates is not predefined by the Speech Manager. Each speech synthesizer provides its own range of speaking rates. Furthermore, any specific rate value will correspond to slightly different rates with different synthesizers. 
  295. Speaking pitches are defined on a musical scale that corresponds to the keys on a standard piano keyboard. By convention, pitches are represented as fixed-point values in the range from 0.000 through 100.000, where 60.000 corresponds to middle C (261.625 Hz) on a conventional piano. Pitches are represented on a logarithmic scale. On this scale, a change of +12 units corresponds to doubling the frequency, while a change of –12 units corresponds to halving the frequency. For a further discussion of pitch values, see “Getting Information About a Speech Channel,” later in this document.
  296. Typical voice frequencies might range from around 90 Hertz for a low-pitched male voice to perhaps 300 Hertz for a high-pitched child’s voice. These frequencies correspond to pitch values of 41.526 and 53.526, respectively.
  297. Changes in speech rate and pitch are effective immediately (as soon as the synthesizer can respond), even if they occur in the middle of a word.
  298. SetSpeechRate
  299.  
  300. The SetSpeechRate routine sets the speaking rate on a designated speech channel.
  301. pascal OSErr SetSpeechRate (SpeechChannel chan, Fixed rate);
  302. Field descriptions
  303. chan    Specific speech channel
  304. rate    Word output speaking rate
  305. DESCRIPTION
  306. The SetSpeechRate routine is used to adjust the speaking rate on a speech channel. The rate parameter is specified as a fixed-point, words per minute value. As a general rule of thumb, “normal” speaking rates range from around 150 WPM to around 180 WPM. It is important when working with speaking rates, however, to keep in mind that users will differ greatly in their ability to understand synthesized speech at a particular rate based upon their level of experience listening to the voice and their ability to anticipate the types of utterances they will encounter.
  307. RESULT CODESnoErr    0    No error    
  308. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  309.  
  310. GetSpeechRate
  311.  
  312. The GetSpeechRate routine returns the speech rate currently active on a designated speech channel.
  313. pascal OSErr GetSpeechRate (SpeechChannel chan, Fixed *rate);
  314. Field descriptions
  315. chan    Specific speech channel
  316. *rate    Pointer to the current speaking rate
  317. DESCRIPTION
  318. The GetSpeechRate routine is used to find out the speaking rate currently active on a speech channel.
  319. RESULT CODESnoErr    0    No error    
  320. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  321.  
  322. SetSpeechPitch
  323.  
  324. The SetSpeechPitch routine sets the speaking pitch on a designated speech channel.
  325. pascal OSErr SetSpeechPitch (SpeechChannel chan, Fixed pitch);
  326. Field descriptions
  327. chan    Specific speech channel
  328. pitch    Frequency of voice
  329. DESCRIPTION
  330. Use the SetSpeechPitch routine to change the current speaking pitch on a speech channel.
  331. RESULT CODESnoErr    0    No error    
  332. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  333.  
  334. GetSpeechPitch
  335.  
  336. The GetSpeechPitch routine returns the current speaking pitch on a designated speech channel.
  337. pascal OSErr GetSpeechPitch (SpeechChannel chan, Fixed *pitch);
  338. Field descriptions
  339. chan    Specific speech channel
  340. pitch    Frequency of voice
  341. DESCRIPTION
  342. The GetSpeechPitch routine is used to find out the speaking pitch currently active on a speech channel.
  343. RESULT CODESnoErr    0    No error    
  344. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  345.  
  346. Putting It All Together
  347.  
  348. The code fragment in Listing 1-4 illustrates many of the routines introduced in this section. The example steps through the list of available voices to find the first female voice. Then it creates a new speech channel and begins speaking. While the voice is speaking, the pitch of the voice is continually adjusted around the original pitch. If the mouse button is pressed while the voice is speaking, the code halts the speech and exits. This example uses the SpeechAvailable and GetVoiceGender routines shown earlier in Listing 1-1 and Listing 1-3.
  349. Listing 1-4    Putting it all together
  350.  
  351. OSErr                        err;
  352. Str255                        myStr = "\pThe bat sat on my hat.";
  353. VoiceSpec                        voice;
  354. VoiceDescription                         vd;
  355. Boolean                        gotVoice = FALSE;
  356. short                        voiceCount, gender, i;
  357. SpeechChannel                        chan;
  358. Fixed                        origPitch, newPitch;
  359.  
  360. if (myStr[0] && SpeechAvailable()) {
  361.     err = CountVoices(&voiceCount);                                        // count the available voices 
  362.     i = 1;
  363.     while ((i <= voiceCount) && ((err=GetIndVoice(i++, &voice)) 
  364.             ==noErr))
  365.         {
  366.         err = GetIndVoice(i++, &voice)) == noErr;
  367.         err = GetVoiceGender(&voice, &gender);
  368.         if ((err == noErr) && (gender == kFemale)) {
  369.             gotVoice = TRUE;
  370.             break;
  371.         }
  372.     }
  373.     if (gotVoice) {
  374.         err = NewSpeechChannel(&voice, &chan);
  375.         if (err == noErr) {
  376.             err = GetSpeechPitch(chan, &origPitch); // cur pitch 
  377.             if (err == noErr)
  378.                 err = SpeakText(chan, &myStr[1], myStr[0]);
  379.             
  380.             i = 0;
  381.             if (err == noErr)
  382.                 while (SpeechBusy() > 0) {
  383.                     CoolAnimationRoutine();
  384.                     newPitch = (i - 4) << 16; // fixed pitch offset 
  385.                     newPitch += origPitch;
  386.                     i = (i + 1) & 7;    // steps from 0 to 7 repeatedly 
  387.                     err = SetSpeechPitch(chan, newPitch);
  388.                     if ((err != noErr) || Button()) {
  389.                         err = StopSpeech(chan);
  390.                         break;
  391.                     }
  392.                 }
  393.             err = DisposeSpeechChannel(chan);
  394.         }
  395.     }
  396.     if (err != noErr)
  397.         NotSoCoolAlertRoutine(err);
  398. Advanced Routines
  399.  
  400. This section describes several advanced or rarely-used Speech Manager routines. You can use them to improve the quality of your application’s speech.
  401. Advanced Speech Controls
  402.  
  403. The StopSpeech routine, described in “Starting and Stopping Speech,” earlier in this document, provides a simple way to interrupt any speech output instantly. In some situations it is preferable to be able to stop speech production at the next natural boundary, such as the next word or the end of the current sentence. StopSpeechAt provides that capability.
  404. Similarly, the PauseSpeechAt routine causes speech to pause at a specified point in the text being spoken; the ContinueSpeech routine resumes speech after it has paused.
  405. In addition to SpeakString and SpeakText, described earlier in this document, the Speech Manager provides a third, more general routine. SpeakBuffer is the low-level speech routine upon which the other two are built. SpeakBuffer provides greater control through the use of an additional flags parameter.
  406. The SpeechBusySystemWide routine tells you if any speech is currently being synthesized in your application or elsewhere on the computer.
  407. StopSpeechAt
  408.  
  409. The StopSpeechAt routine halts speech at a specific point in the text being spoken.
  410. pascal OSErr StopSpeechAt (SpeechChannel chan, long whereToStop);
  411. enum {
  412.     kImmediate                        = 0,
  413.     kEndOfWord                        = 1,
  414.     kEndOfSentence                        = 2
  415. };
  416. Field descriptions
  417. chan    Specific speech channel
  418. whereToStop    Location in text at which speech is to stop 
  419. DESCRIPTION
  420. StopSpeechAt is used to halt the production of speech at a specified point in the text. The whereToStop argument should be set to one of the following constants:
  421. n    The kImmediate constant stops speech output immediately. 
  422. n    The kEndOfWord constant lets speech continue until the current word has been spoken. 
  423. n    The kEndOfSentence constant lets speech continue until the end of the current sentence has been reached. 
  424. This routine returns immediately, although speech output continues until the specified point has been reached.
  425. sWARNING
  426. You must not release the memory associated with the current text buffer until the channel status indicates that the speech channel output is no longer busy.s
  427. If the end of the input text buffer is reached before the specified stopping point, the speech synthesizer will stop at this point. Once the stopping point has been reached, the application is free to release the text buffer. Calling StopSpeechAt with whereToStop equal to kImmediate is equivalent to calling StopSpeech, described on page 14. 
  428. Contrast the StopSpeechAt routine with PauseSpeech, described next.
  429. RESULT CODESnoErr    0    No error    
  430. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  431.  
  432. PauseSpeechAt
  433.  
  434. The PauseSpeechAt routine causes speech to pause at a specified point in the text being spoken.
  435. pascal OSErr PauseSpeechAt (SpeechChannel chan, 
  436.         long whereToPause);
  437. enum {
  438.     kImmediate                        = 0,
  439.     kEndOfWord                        = 1,
  440.     kEndOfSentence                        = 2
  441. };
  442. Field descriptions
  443. chan    Specific speech channel
  444. whereToPause    Location in text at which speech is to pause 
  445. DESCRIPTION
  446. PauseSpeech makes speech production pause at a specified point in the text. The whereToPause parameter should be set to one of these constants: 
  447. n    The kImmediate constant stops speech output immediately. 
  448. n    The kEndOfWord constant lets speech continue until the current word has been spoken. 
  449. n    The kEndOfSentence constant lets speech continue until the end of the current sentence has been reached. 
  450. When the specified point is reached, the speech channel enters the paused state, reflected in the channel’s status. PauseSpeechAt returns immediately, although speech output will continue until the specified point.
  451. If the end of the input text buffer is reached before the specified pause point, speech output pauses at the end of the buffer.
  452. PauseSpeechAt differs from StopSpeech and StopSpeechAt in that a subsequent call to ContinueSpeech, described next, causes the contents of the current text buffer to continue being spoken.
  453. sWARNING
  454. While in a paused state, the last text buffer must remain available at all times and must not move. While paused, the SpeechChannel status indicates outputBusy = true and outputPaused = true.s
  455. RESULT CODESnoErr    0    No error    
  456. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  457.  
  458. ContinueSpeech
  459.  
  460. The ContinueSpeech routine resumes speech after it has been halted by the PauseSpeechAt routine.
  461. pascal OSErr ContinueSpeech (SpeechChannel chan);
  462. Field descriptions
  463. chan    Specific speech channel
  464. DESCRIPTION
  465. At any time after PauseSpeechAt is called, ContinueSpeech may be called to continue speaking from the point at which speech paused. Calling ContinueSpeech on a channel that is not currently in a pause state has no effect; calling it before a pause is effective cancels the pause.
  466. RESULT CODESnoErr    0    No error    
  467. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  468.  
  469. SpeakBuffer
  470.  
  471. The SpeakBuffer routine causes the contents of a text buffer to be spoken, using certain flags to control speech behavior.
  472. pascal OSErr SpeakBuffer (SpeechChannel chan, Ptr textBuf,
  473.                                  long byteLength, long controlFlags);
  474. enum {
  475.     kNoEndingProsody                            = 1,
  476.     kNoSpeechInterrupt                            = 2,
  477.     kPreflightThenPause                            = 4
  478. };
  479. Field descriptions
  480. chan    Specific speech channel
  481. textBuf    Buffer of text
  482. byteLength    Length of textBuf
  483. controlFlags    Control flags to control speech behavior 
  484. DESCRIPTION
  485. When the controlFlags parameter is set to 0, SpeakBuffer behaves identically to SpeakText, described on page 13.
  486. The kNoEndingProsody flag bit is used to control whether or not the speech synthesizer automatically applies ending prosody, the speech tone and cadence that normally occur at the end of a statement. Under normal circumstances (for example, when the flag bit is not set), ending prosody is applied to the speech when the end of the textBuf data is reached. This default behavior can be disabled by setting the kNoEndingProsody flag bit.
  487. Some synthesizers do not speak until the kNoEndingProsody flag bit is reset, or they encounter a period in the text, or textBuf is full. 
  488. The kNoSpeechInterrupt flag bit is used to control the behavior of SpeakBuffer when called on a speech channel that is still busy. When the flag bit is not set, SpeakBuffer behaves similarly to SpeakString and SpeakText, described earlier in this document. Any speech currently being produced on the specified speech channel is immediately interrupted and then the new text buffer is spoken. When the kNoSpeechInterrupt flag bit is set, however, a request to speak on a channel that is still busy processing a prior text buffer will result in an error. The new buffer is ignored and the error synthNotReady is returned. If the prior text buffer has been fully processed, the new buffer is spoken normally. 
  489. The kPreflightThenPause flag bit is used to minimize the latency experienced when attempting to speak. Ordinarily whenever a call to SpeakString, SpeakText, or SpeakBuffer is made, the speech synthesizer must perform a certain amount of initial processing before speech output is heard. This startup latency can vary from a few milliseconds to several seconds depending upon which speech synthesizer is being used. Recognizing that larger startup delays may be detrimental to certain applications, a mechanism is provided to provide the synthesizer a chance to perform any necessary computations at noncritical times. Once the computations have been completed, the speech is able to start instantly. When the kPreflightThenPause flag bit is set, the speech synthesizer will process the input text as necessary to the point where it is ready to begin producing speech output. At this point, the synthesizer will enter a paused state and return to the caller. When the application is ready to produce speech, it should call the ContinueSpeech routine to begin speaking.
  490. RESULT CODESnoErr    0    No error    
  491. synthNotReady    –242    Speech channel is still busy speaking    
  492. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  493.  
  494. SpeechBusySystemWide
  495.  
  496. You can use SpeechBusySystemWide to determine if any speech is currently being synthesized in your application or elsewhere on the computer.
  497. pascal short SpeechBusySystemWide (void);
  498. DESCRIPTION
  499. This routine is useful when you want to ensure that no speech is currently being produced anywhere on the Macintosh computer. SpeechBusySystemWide returns the total number of speech channels currently synthesizing speech on the computer, whether they were initiated by your code or by some other process executing concurrently.
  500. RESULT CODES
  501. None
  502. Converting Text Into Phonemes
  503.  
  504. In some situations it is desirable to convert a text string into its equivalent phonemic representation. This may be useful during the content development process to fine-tune the pronunciation of particular words or phrases. By first converting the target phrase into phonemes, you can see what the synthesizer will try to speak. Then you need only correct the parts that would not have been spoken the way you want.
  505. TextToPhonemes
  506.  
  507. The TextToPhonemes routine converts a designated text to phoneme codes.
  508. pascal OSErr TextToPhonemes (SpeechChannel chan, Ptr textBuf,
  509.                                      long textBytes, Handle phonemeBuf,
  510.                                      long *phonemeBytes);
  511. Field descriptions
  512. chan    Specific speech channel
  513. textBuf    Buffer of text
  514. textBytes    Length of textBuf in bytes
  515. phonemeBuf    Buffer of phonemes
  516. *phonemeBytes    Pointer to length of phonemeBuf in bytes
  517. DESCRIPTION
  518. It may be useful to convert your text into phonemes during application development in order to be able to reduce the amount of memory required to speak. If your application does not require the text-to-phoneme conversion portion of the speech synthesizer, significantly less RAM may be required to speak with some synthesizers. Additionally, you may be able to use a higher quality text-to-phoneme conversion process (even one that does not work in real time) to generate precise phonemic information. This data can then be used with any speech synthesizer to produce better speech.
  519. TextToPhonemes accepts a valid SpeechChannel parameter, a pointer to the characters to be converted into phonemes, the length of the input text buffer in bytes, an application-supplied handle into which the converted phonemes can be written, and a length parameter. On return, the phonemeBytes argument is set to the number of phoneme character bytes that were written into phonemeBuf. The data returned by TextToPhonemes will correspond precisely to the phonemes that would be spoken had the input text been sent to SpeakText instead. All current mode settings are applied to the converted speech. No callbacks are generated while the TextToPhonemes routine is generating its output.
  520. RESULT CODESnoErr    0    No error    
  521. paramErr    –50    Parameter value is invalid    
  522. nilHandleErr    –109    Handle argument is nil    
  523. siUnknownInfoType    –231    Feature not implemented on synthesizer    
  524. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  525.  
  526. Getting Information About a Speech Channel
  527.  
  528. Several additional types of information have been made available for advanced users of the Speech Manager. This information provides more detailed status information for each channel. You can get this information by calling the GetSpeechInfo routine. This function accepts selectors that determine the type of information you want to get.
  529. Note
  530. Throughout this document, there are several references to parameter values specified with fixed-point integer values (pbas, pmod, rate, and volm). Unless otherwise stated, the full range of values of the Fixed data type is valid. However, it is left to the individual speech synthesizer implementation to determine whether or not to use the full resolution and range of the Fixed data type. In the event a specified parameter value lies outside the range supported by a particular synthesizer, the synthesizer will substitute the value closest to the specified value that does lie within its performance specifications.u
  531. GetSpeechInfo
  532.  
  533. The GetSpeechInfo routine returns information about a designated speech channel.
  534. pascal OSErr GetSpeechInfo (SpeechChannel chan, OSType selector,
  535.                                      void *speechInfo);
  536. enum {
  537. soStatus                        = 'stat',                // gets speech output status 
  538. soErrors                        = 'erro',                // gets error status 
  539. soInputMode                        = 'inpt',                // gets current text/phon mode 
  540. soCharacterMode                        = 'char',                // gets current character mode 
  541. soNumberMode                        = 'nmbr',                // gets current number mode 
  542. soRate                        = 'rate',                // gets current speaking rate 
  543. soPitchBase                        = 'pbas',                // gets current baseline pitch 
  544. soPitchMod                        = 'pmod',                // gets current pitch modulation 
  545. soVolume                         = 'volm',                // gets current speaking volume 
  546. soSynthType                        = 'vers',                // gets speech synth version info 
  547. soRecentSync                        = 'sync',                // gets most recent sync message info 
  548. soPhonemeSymbols                        = 'phsy',                 // gets phoneme symbols & ex. words 
  549. soSynthExtension                        = 'xtnd'                // gets synthesizer-specific info 
  550. };
  551. Field descriptions
  552. chan    Specific speech channel
  553. selector    Used to specify data being requested
  554. *speechInfo    Pointer to an information structure
  555. DESCRIPTION
  556. The following list of selectors describes the various types of information that can be obtained from the Speech Manager. The format of the information returned depends on which value is used in the selector field, as follows:
  557. Note
  558. For future code compatibility, use the application programming interface (API) labels instead of literal selector values.u
  559. Field descriptions
  560. stat    Gets various items of status information for the specified channel. Indicates whether any speech audio is being generated, whether or not the channel has paused, how many bytes in the input text have yet to be processed, and the phoneme code for the phoneme that is currently being generated. If inputBytesLeft is 0, the input buffer is no longer needed and can be disposed of. The API label for this selector is soStatus.    
  561.                     typedef SpeechStatusInfo *speechInfo;
  562.                     typedef struct SpeechStatusInfo {
  563.                         Boolean            outputBusy;                     // true = audio playing 
  564.                         Boolean            ouputPaused;                    // true = channel paused 
  565.                         long            inputBytesLeft;                    // bytes left to process 
  566.                         short            phonemeCode;                    // current phoneme code     
  567.                     } SpeechStatusInfo;
  568. erro    Gets saved error information and clears the error registers. This selector lets you poll for various run-time errors that occur during speaking, such as the detection of badly formed embedded commands. Errors returned directly by Speech Manager routines are not reported here. The count field shows how many errors have occurred since the last check. If count is 0 or 1, then oldest and newest will be the same. Otherwise, oldest contains the error code for the oldest unread error and newest contains the error code for the most recent error. Both oldPos and newPos contain the character positions of their respective errors in the original input text buffer. The API label for this selector is soErrors.    
  569.                     typedef SpeechErrorInfo *speechInfo;
  570.                     typedef struct SpeechErrorInfo {
  571.                         short            count;             // # of errs since last check 
  572.                         OSErr            oldest;            // oldest unread error 
  573.                         long            oldPos;            // char position of oldest err
  574.                         OSErr            newest;            // most recent error 
  575.                         long            newPos;            // char position of newest err
  576.                     } SpeechErrorInfo;
  577. inpt    Gets the current value of the text processing mode control. The returned value specifies whether the specified speech channel is currently in text-input mode (TEXT) or phoneme-input mode (PHON). The API label for this selector is soInputMode.    
  578.                     typedef OSType *speechInfo;                                        // TEXT or PHON
  579. char    Gets the current value of the character processing mode control. The returned value specifies whether the specified speech channel is currently processing input characters in normal mode (NORM) or in literal, letter-by-letter, mode (LTRL). The API label for this selector is soCharacterMode.    
  580.                     typedef OSType *speechInfo;    // NORM or LTRL 
  581. nmbr    Gets the current value of the number processing mode control. The returned value specifies whether the specified speech channel is currently processing input character digits in normal mode (NORM) or in literal, digit-by-digit, mode (LTRL). The API label for this selector is soNumberMode.
  582.                     typedef OSType *speechInfo;    // NORM or LTRL 
  583. rate    Gets the current speaking rate in words per minute on the specified channel. Speaking rates are fixed-point values. The API label for this selector is soRate.
  584.                     typedef Fixed *speechInfo;
  585. Note
  586. Words per minute is a convenient, if difficult to define, way of representing speaking rate. Although there is no universally accepted definition of words per minute, it does communicate approximate information about speaking rates. Any specific rate may correspond to different rates on different synthesizers, but the two rates should be reasonably close. More importantly, doubling the rate on a particular synthesizer should halve the time needed to speak any particular utterance.u
  587. pbas    Gets the current baseline pitch for the specified channel. The pitch value is a fixed-point integer that conforms to the following frequency relationship: 
  588.                     Hertz = 440.0 * 2((BasePitch - 69) / 12)
  589.                     BasePitch of 1.0                            ≈    9 Hertz
  590.                     BasePitch of 39.5                            ≈    80 Hertz
  591.                     BasePitch of 45.8                            ≈    115 Hertz
  592.                     BasePitch of 50.4                            ≈    150 Hertz
  593.                     BasePitch of 100.0                            ≈    2637 Hertz
  594. BasePitch values are always positive numbers in the range from 1.0 through 100.0. The API label for this selector is soPitchBase.
  595.                     typedef Fixed *speechInfo;
  596. pmod    Gets the current pitch modulation range for the speech channel. Modulation values range from 0.0 through 100.0. A value of 0.0 corresponds to no modulation and means the channel will speak in a monotone. The API label for this selector is soPitchMod. 
  597.     Nonzero modulation values correspond to pitch and frequency deviations according to the following formula: 
  598.                     Maximum pitch = BasePitch + PitchMod
  599.                     Minimum pitch = BasePitch - PitchMod
  600.                     Maximum Hertz = BaseHertz * 2(+ ModValue / 12)
  601.                     Minimum Hertz = BaseHertz * 2(- ModValue / 12)
  602.                     Given:
  603.                         BasePitch of 46.0                                (≈     115 Hertz),
  604.                         PitchMod of 2.0,
  605.                     Then:
  606.                         Maximum pitch     = 48.0                            (≈131 Hertz),
  607.                         Minimum pitch     = 44.0                            (≈104 Hertz)
  608.                     typedef Fixed *speechInfo;
  609. volm    Gets the current setting of the volume control on the specified channel. Volumes are expressed in fixed-point units ranging from 0.0 through 1.0. A value of 0.0 corresponds to silence, and a value of 1.0 corresponds to the maximum possible volume. Volume units lie on a scale that is linear with amplitude or voltage. A doubling of perceived loudness corresponds to a doubling of the volume. The API label for this selector is soVolume.
  610.                     typedef Fixed *speechInfo;
  611. vers    Gets descriptive information for the type of speech synthesizer being used on the specified speech channel. The API label for this selector is soSynthType.
  612.                     typedef SpeechVersionInfo *speechInfo;
  613.                     typedef struct SpeechVersionInfo {
  614.                         OSType            synthType;                        // always 'ttsc' 
  615.                         OSType            synthSubType;                        // synth flavor 
  616.                         OSType            synthManufacturer;    // synth creator 
  617.                         long            synthFlags;                        // reserved 
  618.                         NumVersion             synthVersion;                         // synth version 
  619.                     } SpeechVersionInfo;
  620. sync    Returns the sync message code for the most recently encountered embedded sync command at the audio output point. If no sync command has been encountered, 0 is returned. Refer to the section “Embedded Speech Commands,” later in this document, for information about sync commands. The API label for this selector is soRecentSync.
  621.                     typedef OSType *speechInfo;
  622. phsy    Returns a list of phoneme symbols and example words defined for the current synthesizer. The input parameter is the address of a handle variable. On return, the PhonemeDescriptor parameter contains a handle to the array of phoneme definitions. Make sure to dispose of the handle when you are done using it. This information is normally used to indicate to the user the approximate sounds corresponding to various phonemes—an important feature in international speech. The API label for this selector is soPhonemeSymbols.
  623.                     typedef PhonemeDescriptor ***speechInfo; // VAR
  624.                                                                          Handle 
  625.                     typedef struct PhonemeInfo {
  626.                         short        opcode;            // opcode for the phoneme 
  627.                         Str15        phStr;            // corresponding char string 
  628.                         Str31        exampleStr;                     // word that shows use of
  629.                                                     // phoneme 
  630.                         short        hiliteStart;                    // part of example word 
  631.                                                     //    to be hilighted as in 
  632.                         short        hiliteEnd;                    // TextEdit selections 
  633.                     } PhonemeInfo;
  634.                     typedef struct PhonemeDescriptor {
  635.                         short                phonemeCount;                      // # of elements 
  636.                         PhonemeInfo                thePhonemes[1];                     // element list 
  637.                     } PhonemeDescriptor;
  638. xtnd    This call supports a general method for extending the functionality of the Speech Manager. It is used to get synthesizer-specific information. The format of the returned data is determined by the specific synthesizer queried. The speechInfo argument should be a pointer to the proper data structure. If a particular synthCreator value is not recognized by the synthesizer, the command is ignored and the siUnknownInfoType code is returned. The API label for this selector is soSynthExtension.
  639.                     typedef SpeechXtndData *speechInfo;
  640.                     typedef struct SpeechXtndData {
  641.                         OSType            synthCreator;     // synth creator ID 
  642.                         Byte            synthData[2];     // data TBD by synth 
  643.                     } SpeechXtndData;
  644. RESULT CODESnoErr    0    No error    
  645. siUnknownInfoType    –231    Feature is not implemented on synthesizer    
  646. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  647.  
  648. Advanced Control Routines
  649.  
  650. The Speech Manager provides numerous control features for sophisticated developers. These controls enable you to set various speaking parameters programmatically and provide a rich set of callback routines that can be used to notify applications of various conditions within the speaking process.  They are extended by many speech synthesizers.
  651. These controls are accessed with the SetSpeechInfo routine. All calls to this routine expect a SpeechChannel parameter, a selector to indicate the desired function, and a pointer to some data. The format of this data depends on the particular selector and is documented in the following routine description.
  652. SetSpeechInfo
  653.  
  654. The SetSpeechInfo routine sets information for a designated speech channel.
  655. pascal OSErr SetSpeechInfo (SpeechChannel chan, OSType selector,
  656.      void *speechInfo);
  657. enum {                                                // Sets the parameter: 
  658.     soInputMode                            = 'inpt',                // current text/phon mode 
  659.     soCharacterMode                            = 'char',                // current character mode 
  660.     soNumberMode                            = 'nmbr',                // current number mode 
  661.     soRate                            = 'rate',                // current speaking rate 
  662.     soPitchBase                            = 'pbas',                // current baseline pitch 
  663.     soPitchMod                            = 'pmod',                // current pitch modulation 
  664.     soVolume                             = 'volm',                // current speaking volume 
  665.     soCurrentVoice                            = 'cvox',                // current speaking voice 
  666.     soCommandDelimiter                            = 'dlim',                // command delimiters 
  667.     soReset                            = 'rset',                // re channel to default state 
  668.     soCurrentA5                            = 'myA5',                // app's A5 on callbacks 
  669.     soRefCon                            = 'refc',                // reference constant 
  670.     soTextDoneCallBack                            = 'tdcb',                // text done callback proc 
  671.     soSpeechDoneCallBack                            = 'sdcb',                // end-of-speech callback proc 
  672.     soSyncCallBack                            = 'sycb',                // sync command callback proc 
  673.     soErrorCallBack                            = 'ercb',                // error callback proc 
  674.     soPhonemeCallBack                            = 'phcb',                // phoneme callback proc 
  675.     soWordCallBack                            = 'wdcb',                // word callback proc 
  676.     soSynthExtension                            = 'xtnd'                // synthesizer-specific info 
  677. };
  678. Field descriptions
  679. chan    Specific speech channel
  680. selector    Used to specify data being requested
  681. *speechInfo    Pointer to an information structure
  682. DESCRIPTION
  683. The following list of selectors outlines the controls available with the Speech Manager. The format of the information returned depends on which value is used in the selector field, as follows:
  684. Note
  685. The Speech Manager supports several callback features that can provide the sophisticated developer with a tight coupling to the speech synthesis process. However, these callbacks must be used carefully. Each is invoked from interrupt level. This means that you may not perform any operations that might cause memory to be allocated, purged, or moved. Although application global variables are also ordinarily not accessible at interrupt time, the soCurrentA5 myA5 selector described in the following text can be used to ask the Speech Manager to point register A5 at your application’s global variables prior to each callback. This makes it fairly painless to access global variables from your callback handlers. If this information worries you, don’t despair. Most information available through callbacks is also available through a GetSpeechInfo call. These calls are more friendly and do not come with the constraints imposed upon callback code. The only drawback is that if you do not poll the information you are interested in often enough, you may miss some of the changes in your speech channel’s status.u
  686. Field descriptions
  687. inpt    Sets the current value of the text processing mode control. The passed value specifies whether the speech channel should be in text-input mode (TEXT) or phoneme-input mode (PHON). Input mode changes take effect as soon as possible; however, the precise latency is dependent upon the specific speech synthesizer. The API label for this selector is soInputMode.
  688.                     typedef OSType *speechInfo;     // TEXT or PHON 
  689. char    Sets the current value of the character processing mode control. The passed value specifies whether the speech channel should be in normal character processing mode (NORM) or literal, letter-by-letter, mode (LTRL). Character mode changes take effect as soon as possible; however, the precise latency is dependent upon the specific speech synthesizer. The API label for this selector is soCharacterMode.
  690.                     typedef OSType *speechInfo;     // NORM or LTRL 
  691. nmbr    Sets the current value of the number processing mode control. The passed value specifies whether the specified speech channel should be in normal number processing mode (NORM) or in literal, digit-by-digit, mode (LTRL). The number mode changes take effect as soon as possible. However, the precise latency is dependent upon the specific speech synthesizer. The API label for this selector is soNumberMode.
  692.                     typedef OSType *speechInfo;     // NORM or LTRL 
  693. rate    Sets the speaking rate in words per minute on the specified channel. Speaking rates are fixed-point values. All values are valid; however, specific synthesizers will not necessarily be able to speak at all possible rates. The API label for this selector is soRate.
  694.                     typedef Fixed *speechInfo;
  695. pbas    Changes the current baseline pitch for the specified channel. The pitch value is a fixed-point integer that conforms to the following frequency relationship:
  696.                     Hertz = 440.0 * 2((BasePitch - 69) / 12)
  697.                     BasePitch of 1.0                            ≈    9 Hertz
  698.                     BasePitch of 39.5                            ≈    80 Hertz
  699.                     BasePitch of 45.8                            ≈     115 Hertz
  700.                     BasePitch of 50.4                            ≈    150 Hertz
  701.                     BasePitch of 100.0                            ≈    2637 Hertz
  702.     BasePitch values are always positive numbers in the range from 1.0 through 100.0.
  703.                     typedef Fixed *speechInfo;
  704.     The API label for this selector is soPitchBase.
  705. pmod    Changes the current pitch modulation range for the speech channel. Modulation values range from 0.0 through 100.0. A value of 0.0 corresponds to no modulation and means the channel will speak in a monotone. Nonzero modulation values correspond to pitch and frequency deviations according to the following formula:
  706.                     Maximum pitch                    = BasePitch + PitchMod
  707.                     Minimum pitch                    = BasePitch - PitchMod
  708.                     Maximum Hertz                    = BaseHertz * 2(+ ModValue / 12)
  709.                     Minimum Hertz  = BaseHertz * 2(- ModValue / 12)
  710.                     Given : 
  711.                         BasePitch of 46.0                            (≈115 Hertz),
  712.                         PitchMod of 2.0,
  713.                     Then:
  714.                         Maximum pitch         = 48.0                    (≈131 Hertz),
  715.                         Minimum pitch     = 46.0                        (≈104 Hertz)
  716.  
  717.                     typedef Fixed *speechInfo;
  718.     The API label for this selector is soPitchMod.
  719. volm    Changes the current speaking volume on the specified channel. Volumes are expressed in fixed-point units ranging from 0.0 through 1.0 . A value of 0.0 corresponds to silence, and a value of 1.0 corresponds to the maximum possible volume. Volume units lie on a scale that is linear with amplitude or voltage. A doubling of perceived loudness corresponds to a doubling of the volume. The API label for this selector is soVolume.
  720.                     typedef Fixed *speechInfo;
  721. cvox    Changes the current voice on the current speech channel to the specified voice. Note that this control call will return an incompatibleVoice error if the specified voice is incompatible with the speech synthesizer associated with the speech channel. The API label for this selector is soCurrentVoice.
  722.                     typedef VoiceSpec *speechInfo;
  723. dlim    Sets the delimiter character strings for embedded commands. The start of an embedded command is determined by comparing the input characters to the start-command delimiter string. Likewise, the end of a command is determined by comparing the input characters to the end-command delimiter string. Command delimiter strings are either 1 or 2 bytes in length. If a single byte delimiter is desired, it should be followed by a null (0) byte. Delimiter characters must come from the set of printable characters. If the delimiter strings are empty, this will have the effect of disabling embedded command processing. Care must be taken not to choose delimiter strings that might occur naturally in the text to be spoken. The API label for this selector is soCommandDelimiter.
  724.                     typedef             DelimiterInfo *speechInfo;
  725.                     typedef             struct DelimiterInfo {
  726.                     Byte             startDelimiter[2];                             // defaults to "[[" 
  727.                     Byte             endDelimiter[2];                            // defaults to "]]" 
  728.                     } DelimiterInfo;
  729. rset    Resets the speech channel to its default states. The speechInfo parameter should be set to 0. Specific synthesizers may provide other reset capabilities. The API label for this selector is soReset.
  730.                     typedef long *speechInfo;
  731. myA5    An application uses this selector to request that the speech synthesizer set up an A5 world prior to all callbacks. In order for an application to access any of its global data, it is necessary that register A5 contain the correct value, since all global variables are referenced relative to register A5. If you pass a non-null value in the speechInfo parameter, the speech synthesizer will set register A5 to this value just before it calls one of your callback routines. The A5 register is restored to its original value when your callback routine returns. The API label for this selector is soCurrentA5.
  732.                     typedef Ptr speechInfo;
  733.     A typical application would make the call to SetSpeechInfo with code like the following:
  734.                     myA5 = SetCurrentA5();
  735.                     err = SetSpeechInfo (mySpeechChannel, soCurrentA5,
  736.                              myA5);
  737. refc    Sets the reference constant associated with the specified channel. All callbacks generated for this channel will return this reference constant for use by the application. The application can use this value any way it wants to. The API label for this selector is soRefCon.
  738.                     typedef long *speechInfo;
  739. tdcb    Enables the callback that signals that text input processing is done. Your callback routine is invoked when the current buffer of input text has been processed and is no longer needed by the speech synthesizer. This callback does not indicate that the synthesizer is finished speaking the text (see the sdcb callback description, next), merely that the input text has been fully processed and is no longer needed by the speech synthesizer. This callback can be disabled by passing a null ProcPtr in the speechInfo parameter. When your callback routine is invoked, you have two options. If you set the nextBuf, byteLen, and controlFlags variables before returning, you will enable the speech synthesizer to continue speaking without any interruption in the output. If you set the nextBuf parameter to null, you are indicating that you have no more text to speak. The controlFlags parameter is defined as in SpeakBuffer. The API label for this selector is soTextDoneCallBack.
  740.                     typedef Ptr speechInfo;
  741.                     pascal void MyInputDoneCallback (SpeechChannel
  742.                          chan, long refCon, Ptr *nextBuf,
  743.                          long *byteLen, long *controlFlags);
  744. sdcb    Enables an end-of-speech callback. Your callback routine is called whenever an input text stream has been completely processed and spoken. When your callback routine is invoked, you can be certain that the speech channel is now idle and no audio is being generated. This callback can be disabled by passing a null ProcPtr in the speechInfo parameter. The API label for this selector is soSpeechDoneCallBack.
  745.                     typedef Ptr speechInfo;
  746.                     pascal void MyEndOfSpeechCallback (SpeechChannel
  747.                          chan, long refCon);
  748. sycb    Enables the sync command callback. Your callback routine is invoked when the text following a sync embedded command is about to be spoken. This callback can be disabled by passing a null ProcPtr in the speechInfo parameter. See “Embedded Speech Commands,” later in this document, for a description of how to use sync commands. The API label for this selector is soSyncCallBack.
  749.                     typedef Ptr speechInfo;
  750.                     pascal void MySyncCommandCallback (SpeechChannel
  751.                          chan, long refCon, OSType syncMessage);
  752. ercb    Enables error callbacks. Your callback routine is called whenever an error occurs during the processing of an input text stream. Errors can result from syntax problems in the input text, insufficient CPU processing speed (such as an audio data underrun), or other conditions that may arise during the speech conversion process. If error callbacks have not been enabled, when an error condition is detected, the Speech Manager will save its value. The error codes can then be read using the GetSpeechInfo status selector soErrors (erro). The error callback can be disabled by passing a null ProcPtr in the speechInfo parameter. The API label for this selector is soErrorCallBack.
  753.                     typedef Ptr speechInfo;
  754.                     pascal void MyErrorCallback (SpeechChannel chan,
  755.                          long refCon, OSErr error, long bytePos);
  756. phcb    Enables phoneme callbacks. Your callback routine is invoked for each phoneme generated by the speech synthesizer just before the phoneme is actually spoken. This callback can be disabled by passing a null ProcPtr in the speechInfo parameter. The API label for this selector is soPhonemeCallBack.
  757.                     typedef Ptr speechInfo;
  758.                     pascal void MyPhonemeCallBack (SpeechChannel chan,
  759.                          long refCon, short phonemeOpcode);
  760. wdcb    Enables word callbacks. Your callback routine is invoked for each word generated by the speech synthesizer just before the word is actually spoken. This callback can be disabled by passing a nil ProcPtr in the speechInfo parameter. The API label for this selector is soWordCallBack.
  761.                     typedef Ptr speechInfo;
  762.                     pascal void MyWordCallback (SpeechChannel chan, 
  763.                         long refCon, long wordPos, short wordLen);
  764. xtnd    This call supports a general method for extending the functionality of the Speech Manager. It is used to set synthesizer-specific information. The speechInfo argument should be a pointer to the appropriate data structure. If a particular synthCreator value is not recognized by the synthesizer, the command is ignored and an siUnknownInfoType code is returned. The API label for this selector is soSynthExtension.
  765.                     typedef SpeechXtndData *speechInfo;
  766.                     typedef struct SpeechXtndData {
  767.                         OSType            synthCreator;             // synth creator ID 
  768.                         Byte            synthData[2];     // data TBD by synth 
  769.                     } SpeechXtndData;
  770. RESULT CODESnoErr    0    No error    
  771. paramErr    –50    Parameter value is invalid    
  772. siUnknownInfoType    –231    Feature is not implemented on synthesizer    
  773. incompatibleVoice    –245    Specified voice cannot be used with synthesizer    
  774. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  775.  
  776. Application-Defined Pronunciation Dictionaries
  777.  
  778. No matter how sophisticated a speech synthesis system is, there will always be words that it does not automatically pronounce correctly. The clearest instance of words that are often mispronounced is the class of proper names (names of people, place names, and so on). 
  779. One way to get around this fundamental limitation is to use a dictionary of pronunciations. Whenever a speech synthesizer needs to determine the proper phonemic representation for a particular word, it first looks for the word in its dictionaries. Pronunciation dictionary entries contain information that enables precise conversion between text and the correct phoneme codes. They also provide stress, intonation, and other information to help speech synthesizers produce more natural speech. If the word in question is found in the dictionary, then the synthesizer uses the information from the dictionary entry rather than relying on its own letter-to-sound rules. The use of phonemes is described in “Summary of Phonemes and Prosodic Controls,” later in this document.
  780. The Speech Manager word storage format provides high-quality data that is interchangeable between speech synthesizers. The Speech Manager also uses an easily extensible dictionary structure that does not affect the usability of existing dictionaries.
  781. It is assumed that application-defined pronunciation dictionaries will reside in RAM when in use. The run-time structure of dictionary data presumably depends on the specific needs of particular speech synthesizers and will therefore differ from the structure of the dictionaries as stored on disk.
  782. Associating a Dictionary With a Speech Channel
  783.  
  784. The following routines can be used to associate an application-defined pronunciation dictionary with a particular speech channel.
  785. UseDictionary
  786.  
  787. The UseDictionary routine associates a designated dictionary with a specific speech channel.
  788. pascal OSErr UseDictionary (SpeechChannel chan, Handle
  789.          dictionary);
  790. Field descriptions
  791. chan    Specific speech channel
  792. dictionary    Handle to the specified dictionary
  793. DESCRIPTION
  794. The speech synthesizer will attempt to use the dictionary data pointed to by the dictionary handle argument to augment the built-in pronunciation rules on the specified speech channel. The synthesizer will use whatever elements of the dictionary resource it considers useful to the speech conversion process. After returning from UseDictionary, the caller is free to release any storage allocated for the dictionary handle. The search order for application-provided dictionaries is last in, first searched.
  795. All details of how an application-provided dictionary is represented within the speech synthesizer are dependent on the specific synthesizer implementation and are totally private to the synthesizer.
  796. RESULT CODESnoErr    0    No error    
  797. memFullErr    –108    Not enough memory to use new dictionary    
  798. badDictFormat    –246    Format problem with pronunciation dictionary    
  799. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  800.  
  801. Pronunciation Dictionary Data Format
  802.  
  803. Each application-defined pronunciation dictionary is implemented as a single resource of type 'dict'. To read the dictionary contents, the system first reads the resource into memory using Resource Manager routines.
  804. An application dictionary contains the following information:total byte length    (long)    (Length is all-inclusive)    
  805. atom type    (long)        
  806. format version    (long)        
  807. script code    (short)        
  808. language code    (short)        
  809. region code    (short)        
  810. date last modified    (long)    (Seconds since January 1, 1904)    
  811. reserved(4)    (long)        
  812. entry count    (long)        
  813. list of entries            
  814.  
  815. The currently defined atom type is'dict '    Æ    Dictionary    
  816.  
  817. Each entry consists of the following:entry byte length    (short)    (Length is all-inclusive)    
  818. entry type    (short)        
  819. field count    (short)        
  820. list of fields            
  821.  
  822. The currently defined entry types are the following:0x00    Æ    Null entry    
  823. 0x01 to 0x20    Æ    Reserved    
  824. 0x21    Æ    Pronunciation entry    
  825. 0x22    Æ    Abbreviation entry    
  826.  
  827. Each field consists of the following:field byte length    (short)    (Length is all-inclusive minus padding)    
  828. field type    (short)        
  829. field data    (char[])    (Data is padded to word boundary)    
  830.  
  831. The currently defined field types are the following:0x00    Æ    Null field    
  832. 0x01 to 0x20    Æ    Reserved    
  833. 0x21    Æ    Word represented in textual format.    
  834. 0x22    Æ    Phonemic pronunciation including a complete set of syllable, lexical stress, word prominence, and prosodic markers represented in textual format    
  835. 0x23    Æ    Part-of-speech code    
  836.  
  837. Creating and Editing Dictionaries
  838.  
  839. There is no built-in support for creating and editing speech dictionaries. You can create dictionary resources using any of the available resource editing tools such as the MPW Rez tool or ResEdit. Of course, you can also fairly easily develop routines to edit the dictionary structure from within the application. At the present time, no assumption should be made that the entries in a dictionary are stored in sorted order.
  840. Advanced Voice Information Routines
  841.  
  842. Ordinarily, an application should need to use only the GetVoiceDescription routine to access information about a particular voice. Occasionally, however, it may be necessary to obtain more detailed information by using the GetVoiceInfo routine.
  843. GetVoiceInfo
  844.  
  845. The GetVoiceInfo routine returns information about a specified voice channel beyond that obtainable through the GetVoiceDescription routine.
  846. pascal OSErr GetVoiceInfo (VoiceSpec *voice, OSType selector,
  847.      void *voiceInfo);
  848.     typedef VoiceDescription *voiceInfo;
  849.     typedef VoiceFileInfo *voiceInfo;
  850.  
  851.     typedef struct VoiceFileInfo {
  852.     FSSpec            fileSpec;                // vol, dir, name info for voice file 
  853.     short            resID;                // resource ID of voice in the file 
  854. } VoiceFileInfo;
  855. enum {
  856.     soVoiceDescription                            = 'info',                // gets basic voice info 
  857.     soVoiceFile                            = 'fref'                // gets voice file ref info 
  858. };
  859. Field descriptions
  860. *voice    Specific speech channel
  861. selector    Used to specify data being requested
  862. *voiceInfo    Pointer to an information structure
  863. DESCRIPTION
  864. This function accepts selectors that determine the type of information you want to get. The format of the information returned depends on which value is used in the selector field, as follows:
  865. Field descriptions
  866. info    Gets basic information for the specified voice. The structure returned is functionally equivalent to the VoiceDescription data structure in GetVoiceDescription, described earlier in this document. To maximize compatibility with future versions of the Speech Manager, the application must set the length field of the VoiceDescription structure to the size of the existing record before calling GetVoiceInfo, which then returns the size of the new record.
  867. fref    Gets file reference information for specified voice; normally only used by speech synthesizers to access voice disk files directly.
  868. RESULT CODESnoErr    0    No error    
  869. memFullErr    –108    Not enough memory to load voice into memory    
  870. voiceNotFound    –244    Voice resource not found    
  871.  
  872. Embedded Speech Commands
  873.  
  874. This section describes how you can insert commands directly into the input text to control or modify the spoken output. When processing input text data, speech synthesizers look for special sequences of characters called delimiters. These character sequences are usually defined to be unusual pairings of printable characters that would not normally appear in the text. When a begin command delimiter string is encountered in the text, the following characters are assumed to contain one or more commands. The synthesizer will attempt to parse and process these commands until an end command delimiter string is encountered.
  875. Embedded Speech Command Syntax
  876.  
  877. By default, the begin command and end command delimiters are defined to be [[ and ]]. The syntax of embedded command blocks is given below, according to these rules: 
  878. n    Items enclosed in angle brackets (< and >) represent logical units that are either defined further below or are atomic units that should be self-explanatory. 
  879. n    Items enclosed in brackets are optional. 
  880. n    Items followed by an ellipsis (…) may be repeated one or more times. 
  881. n    For items separated by a vertical bar (|), any one of the listed items may be used. 
  882. n    Multiple space characters between tokens may be used if desired. 
  883. n    Multiple commands should be separated by semicolons.
  884. All other characters that are not enclosed between angle brackets must be entered literally. There is no limit to the number of commands that can be included in a single command block.
  885.  
  886. Identifier    Syntax    
  887. CommandBlock    <BeginDelimiter> <CommandList> <EndDelimiter>    
  888. BeginDelimiter    <String1> | <String2>    
  889. EndDelimiter    <String1> | <String2>    
  890. CommandList     <Command> [; <Command>]…    
  891. Command     <CommandSelector> [Parameter]…    
  892. CommandSelector    <OSType>    
  893. Parameter    <OSType> | <String1> | <String2> | <StringN> | <FixedPointValue> |<32BitValue> | <16BitValue> | <8BitValue>    
  894. String1    <QuoteChar> <Character> <QuoteChar>    
  895. String2    <QuoteChar> <Character> <Character> <QuoteChar>    
  896. StringN    <QuoteChar> [<Character>]… <QuoteChar>    
  897. QuoteChar    " | '    
  898. OSType    <4 character pattern (e.g., RATE, vers, aBcD)>    
  899. Character    <Any printable character (example A, b, *, #, x)>    
  900. FixedPointValue    <Decimal number: 0.0000 £ N £ 65535.9999>    
  901. 32BitValue    <OSType> | <LongInt> | <HexLongInt>    
  902. 16BitValue    <Integer> | <HexInteger>    
  903. 8BitValue    <Byte> | <HexByte>    
  904. LongInt    <Decimal number: 0 £ N £ 4294967295>    
  905. HexLongInt    <Hex number: 0x00000000 £ N £ 0xFFFFFFFF>    
  906. Integer    <Decimal number: 0 £ N £ 65535>    
  907.     (continued)    
  908. HexInteger    <Hex number: 0x0000 £ N £ 0xFFFF>    
  909. Byte    <Decimal number: 0 £ N £ 255>    
  910. HexByte    <Hex number: 0x00 £ N £ 0xFF>    
  911. Here is the embedded command syntax structure:
  912. Embedded Speech Command Set
  913.  
  914. Table 1-1 outlines the set of currently defined embedded speech commands.
  915. Table 1-1    Embedded speech commands(continued)
  916. Command    Selector    Command syntax and description    
  917. Version    vers    vers <Version>
  918. Version::= <32BitValue>
  919. This command informs the synthesizer of the format version that will be used in subsequent commands. This command is optional but is highly recommended. The current version is 1.    
  920. Delimiter    dlim    dlim <BeginDelimiter> <EndDelimiter>
  921. The delimiter command specifies the character sequences that mark the beginning and end of all subsequent commands. The new delimiters take effect at the end of the current command block. If the delimiter strings are empty, an error is generated. (Contrast this behavior with the dlim function of SetSpeechInfo.)    
  922. Comment    cmnt    cmnt [Character]…
  923. This command enables a developer to insert a comment into a text stream for documentation purposes. Note that all characters following the cmnt selector up to the <EndDelimiter> are part of the comment.    
  924. Reset    rset    rset <32BitValue>
  925. The reset command will reset the speech channel’s settings back to the default values. The parameter should be set to 0.    
  926.         (continued)    
  927. Baseline pitch    pbas    pbas [+ | -] <Pitch>
  928. Pitch ::= <FixedPointValue>
  929. The baseline pitch command changes the current pitch for the speech channel. The pitch value is a fixed-point number in the range 1.0 through 100.0 that conforms to the frequency relationship 
  930.  
  931. Hertz = 440.0 * 2((Pitch – 69) / 12)
  932.  
  933. If the pitch number is preceded by a + or – character, the baseline pitch is adjusted relative to its current value. Pitch values are always positive numbers. For further details, see “SetSpeechInfo,” earlier in this document.    
  934. Pitch modulation    pmod    pmod [+ | -] <ModulationDepth>
  935. ModulationDepth ::= <FixedPointValue>
  936. The pitch modulation command changes the modulation range for the speech channel. The modulation value is a fixed-point number in the range 0.0 through 100.0 that conforms to the following pitch and frequency relationships:
  937.  
  938. Maximum pitch = BasePitch + PitchMod
  939. Minimum pitch = BasePitch - PitchMod
  940. Maximum Hertz = BaseHertz * 2(+ ModValue / 12)
  941. Minimum Hertz = BaseHertz * 2(– ModValue / 12)
  942.  
  943. A value of 0.0 corresponds to no modulation and will cause the speech channel to speak in a monotone. If the modulation depth number is preceded by a + or – character, the pitch modulation is adjusted relative to its current value. For further details, see “SetSpeechInfo,” earlier in this document.    
  944. Speaking rate    rate    rate [+ | -] <WordsPerMinute>
  945. WordsPerMinute ::= <FixedPointValue>
  946. The speaking rate command sets the speaking rate in words per minute on the speech channel. If the rate value is preceded by a + or – character, the speaking rate is adjusted relative to its current value.    
  947.         (continued)    
  948. Volume    volm    volm [+ | -] <Volume>
  949. Volume::= <FixedPointValue>
  950. The volume command changes the speaking volume on the speech channel. Volumes are expressed in fixed-point units ranging from 0.0 through 1.0 . A value of 0.0 corresponds to silence, and a value of 1.0 corresponds to the maximum possible volume. Volume units lie on a scale that is linear with amplitude or voltage. A doubling of perceived loudness corresponds to a doubling of the volume.    
  951. Sync    sync    sync <SyncMessage>
  952. SyncMessage::= <32BitValue>
  953. The sync command causes a callback to the application’s sync command callback routine. The callback is made when the audio corresponding to the next word begins to sound. The callback routine is passed the SyncMessage value from the command. If the callback routine has not been defined, the command is ignored. For further details, see “SetSpeechInfo,” earlier in this document.    
  954. Input mode    inpt    inpt TX | TEXT | PH | PHON
  955. This command switches the input processing mode to either normal text mode or raw phoneme mode.    
  956. Character mode    char    char NORM | LTRL
  957. The character mode command sets the word speaking mode of the speech synthesizer. When NORM mode is selected, the synthesizer attempts to automatically convert words into speech. This is the most basic function of the text-to-speech synthesizer. When LTRL mode is selected, the synthesizer speaks every word, number, and symbol letter by letter. Embedded command processing continues to function normally, however.    
  958. Number mode    nmbr    nmbr NORM | LTRL
  959. The number mode command sets the number speaking mode of the speech synthesizer. When NORM mode is selected, the synthesizer attempts to automatically speak numeric strings as intelligently as possible. When LTRL mode is selected, numeric strings are spoken digit by digit.    
  960.         (continued)      
  961. Silence    slnc    slnc <Milliseconds>
  962. Milliseconds ::= <32BitValue>
  963. The silence command causes the synthesizer to generate silence for the specified amount of time.    
  964. Emphasis    emph    emph + | -
  965. The emphasis command causes the next word to be spoken with either greater emphasis or less emphasis than would normally be used. Using + will force added emphasis, while using – will force reduced emphasis.    
  966. Synthesizer-Specific    xtnd    xtnd <SynthCreator> [parameter]
  967. SynthCreator ::= <OSType>
  968. The extension command enables synthesizer-specific commands to be embedded in the input text stream. The format of the data following SynthCreator is entirely dependent on the synthesizer being used. If a particular SynthCreator is not recognized by the synthesizer, the command is ignored but no error is generated.    
  969.  
  970. Synthesizers often support embedded commands that extend the set given in Table 1-1. 
  971. Embedded Speech Command Error Reporting
  972.  
  973. While embedded speech commands are being processed, several types of errors may be detected and reported to your application. If you have set up an error callback handler with the soErrorCallBack selector of the SetSpeechInfo routine (described earlier), you will be notified once for every error that is detected. If you have not enabled error callbacks, you can still obtain information about the errors encountered by calling GetSpeechInfo with the soErrors selector (also described earlier). The following errors are detected during processing of embedded speech commands:badParmVal    –245    Parameter value is invalid    
  974. badCmdText    –246    Embedded command syntax or parameter problem    
  975. unimplCmd    –247    Embedded command is not implemented on synthesizer    
  976. unimplMsg    –248    Raw phoneme text contains invalid characters    
  977. badVoiceID    –250    Specified voice has not been preloaded    
  978. badParmCount    –252    Incorrect number of embedded command arguments found    
  979.  
  980.  
  981. Summary of Phonemes and Prosodic Controls
  982.  
  983. This section summarizes the phonemes and prosodic controls used by American English speech synthesizers.
  984. Phoneme Set
  985.  
  986. Table 1-2 summarizes the set of standard phonemes recognized by American English speech synthesizers.
  987. In this description, it is assumed that specific rules and markers apply only to general American English. Other languages and dialects require different phoneme inventories. Phonemes divide into two groups: vowels and consonants. All vowel symbols are uppercase pairs of letters. For consonants, in cases in which the correspondence between the consonant and its symbol is apparent, the symbol is that lowerrcase consonant; in other cases, the symbol is an uppercase consonant. Within the example words, the individual sounds being exemplified appear in bold face.
  988. Table 1-2    American English phoneme symbols(continued)
  989. Symbol    Example    Opcode    Symbol    Example    Opcode    
  990. AE    bat    2    b    bin    18    
  991. EY    bait    3    C    chin    19    
  992. AO    caught    4    d    din    20    
  993. AX    about    5    D    them    21    
  994. IY    beet    6    f    fin    22    
  995. EH    bet    7    g    gain    23    
  996. IH    bit    8    h    hat    24    
  997. AY    bite    9    J    gin    25    
  998. IX    roses    10    k    kin    26    
  999. AA    cot    11    l    limb    27    
  1000. UW    boot    12    m    mat    28    
  1001. UH    book    13    n    nat    29    
  1002. UX    bud    14    N    tang    30    
  1003. OW    boat    15    p    pin    31    
  1004. AW    bout    16    r    ran    32    
  1005. OY    boy    17    s    sin    33    
  1006.             S    shin    34    
  1007.             t    tin    35    
  1008.             T    thin    36    
  1009.             v    van    37    
  1010.             w    wet    38    
  1011.                 (continued)        
  1012.             y    yet    39    
  1013. %    silence    0    z    zen    40    
  1014. @    breath intake    1    Z    genre    41    
  1015.  
  1016. Note
  1017. The “silence” phoneme (%) and the “breath” phoneme (@) may be lengthened or shortened like any other phoneme.u
  1018. Prosodic Controls
  1019.  
  1020. The symbols listed in Table 1-3 are recognized as modifiers to the basic phonemes described in the preceding section. They can be used to more precisely control the quality of speech that is described in terms of raw phonemes.
  1021. Table 1-3    Prosodic control symbols(continued)
  1022. Type    Symbol        Description of effect        
  1023. Lexical stress:            Marks stress within a word        
  1024.   Primary stress    1    anticipation    AEnt2IHsIXp1EYSAXn   (“anticipation”)        
  1025.   Secondary stress    2    anticipation            
  1026. Syllable breaks:            Marks syllable breaks within a word        
  1027.   Syllable mark    =    (equal)    AEn=t2IH=sIX=p1EY=SAXn (“anticipation”)Marks the beginning of a word (required)        
  1028. Word prominence:                    
  1029.   Unstressed    ~    (asciitilde)    Used for words with minimal information content        
  1030.   Normal stress    _    (underscore)    Used for information-bearing words        
  1031.   Emphatic stress    +    (plus)    special emphasis for a wordPlaced before the affected phonemepitch will rise on the following phoneme        
  1032. Prosodic                    
  1033.   Pitch rise    /    (slash)            
  1034.   Pitch fall    \    (backslash)    pitch will fall on the following phoneme        
  1035.   Lengthen   phoneme    >    (greater)    lengthen the duration of the following phoneme        
  1036.   Shorten phoneme    <    (less)    shorten the duration of the following phoneme        
  1037.                 (continued)    
  1038. Punctuation:            Pitch effect    Timing effect    
  1039.     .    (period)    Sentence final fall    Pause follows    
  1040.     ?    (question)    Sentence final rise    Pause follows    
  1041.     !    (exclam)    Sentence final sharp fall    Pause follows    
  1042.     …    (ellipsis)    Clause final level    Pause follows    
  1043.     ,    (comma)    Continuation rise    Short pause follows    
  1044.     ;    (semicolon)    Continuation rise     Short pause follows    
  1045.     :    (colon)    Clause final level     Short pause follows    
  1046.     (    (parenleft)    Start reduced range    Short pause precedes    
  1047.     )    (parenright)    End reduced range    Short pause follows    
  1048.     “
  1049. ‘    (quotedblleft, quotesingleleft)    Varies    Varies    
  1050.     ”
  1051. ’    (quotedblright, quotesingleright)    Varies    Varies    
  1052.     -    (hyphen)    Clause-final level    Short pause follows    
  1053.     &    (ampersand)    Forces no addition of silence between phonemes        
  1054.  
  1055. Specific pitch contours associated with these punctuation marks may vary according to other considerations in the analysis of the text, such as whether a question is rhetorical or begins with a wh question word, so the above effects should be regarded only as guidelines and not absolute. This also applies to the timing effects, which will vary according to the current rate setting.
  1056. The prosodic control symbols (/, \, <, and >) may be concatenated to provide more exaggerated, cumulative effects. The specific nature of the effect is dependent on the speech synthesizer. Speech synthesizers also often extend or enhance the controls described in this section. 
  1057.  
  1058. Summary of the Speech Manager
  1059.  
  1060. Constants
  1061.  
  1062. #define gestaltSpeechAttr                                    'ttsc'        // Gestalt Manager selector for speech
  1063.                                                  attributes 
  1064. enum {
  1065.  gestaltSpeechMgrPresent                                    = 0        // Gestalt bit that indicates that Speech
  1066.                                                 Manager exists 
  1067. };
  1068.  
  1069. #define kTextToSpeechSynthType                                                    'ttsc'            // text-to-speech
  1070.                                                                 synthesizer component type 
  1071. #define kTextToSpeechVoiceType                                                    'ttvd'            // text-to-speech voice
  1072.                                                                 resource type 
  1073. #define kTextToSpeechVoiceFileType                                                    'ttvf'            // text-to-speech voice file
  1074.                                                                 type 
  1075. #define kTextToSpeechVoiceBundleType                                                    'ttvb'            // text-to-speech voice
  1076.                                                                 bundle file type 
  1077.  
  1078. enum {            // Speech Manager error codes (range from 240 - 259) 
  1079.     noSynthFound                            = -240,
  1080.     synthOpenFailed                            = -241,
  1081.     synthNotReady                            = -242,
  1082.     bufTooSmall                            = -243,
  1083.     voiceNotFound                            = -244,
  1084.     incompatibleVoice                            = -245,
  1085.     badDictFormat                            = -246,
  1086.     badPhonemeText                            = -247
  1087. };
  1088.  
  1089. enum {                    // constants for SpeakBuffer and text done callback
  1090.                      controlFlags bits 
  1091.     kNoEndingProsody                                = 1,
  1092.     kNoSpeechInterrupt                                = 2,
  1093.     kPreflightThenPause                                = 4
  1094. };
  1095. enum {                    // constants for StopSpeechAt and PauseSpeechAt 
  1096.     kImmediate                        = 0,
  1097.     kEndOfWord                        = 1,
  1098.     kEndOfSentence                        = 2
  1099. };
  1100.  
  1101. // GetSpeechInfo & SetSpeechInfo selectors 
  1102. #define soStatus                                        'stat'
  1103. #define soErrors                                        'erro'
  1104. #define soInputMode                                        'inpt'
  1105. #define soCharacterMode                                        'char'
  1106. #define soNumberMode                                        'nmbr'
  1107. #define soRate                                        'rate'
  1108. #define soPitchBase                                        'pbas'
  1109. #define soPitchMod                                        'pmod'
  1110. #define soVolume                                        'volm'
  1111. #define soSynthType                                        'vers'
  1112. #define soRecentSync                                        'sync'
  1113. #define soPhonemeSymbols                                        'phsy'
  1114. #define soCurrentVoice                                        'cvox'
  1115. #define soCommandDelimiter                                        'dlim'
  1116. #define soReset                                        'rset'
  1117. #define soCurrentA5                                        'myA5'
  1118. #define soRefCon                                        'refc'
  1119. #define soTextDoneCallBack                                        'tdcb'
  1120. #define soSpeechDoneCallBack                                        'sdcb'
  1121. #define soSyncCallBack                                        'sycb'
  1122. #define soErrorCallBack                                        'ercb'
  1123. #define soPhonemeCallBack                                        'phcb'
  1124. #define soWordCallBack                                        'wdcb'
  1125. #define soSynthExtension                                        'xtnd'
  1126.  
  1127. // speaking mode constants 
  1128. #define modeText                                'TEXT'     // input mode constants 
  1129. #define modeTX                                'TX'
  1130. #define modePhonemes                                'PHON'
  1131. #define modePH                                'PH'
  1132. #define modeNormal                                'NORM'         // character mode and number mode constants 
  1133. #define modeLiteral                                'LTRL'
  1134. enum {                                                // GetVoiceInfo selectors 
  1135.     soVoiceDescription                            = 'info',                // gets basic voice info 
  1136.     soVoiceFile                            = 'fref'                // gets voice file ref info 
  1137. };
  1138. enum {kNeuter = 0, kMale, kFemale};                                                // returned in gender field below 
  1139. Data Types
  1140.  
  1141. typedef struct SpeechChannelRecord {
  1142.     long data[1];
  1143. } SpeechChannelRecord;
  1144.  
  1145. typedef SpeechChannelRecord *SpeechChannel;
  1146.  
  1147. typedef struct VoiceSpec {
  1148.     OSType            creator;                // creator ID of required synthesizer 
  1149.     OSType            id;                // voice ID on the specified synth 
  1150. } VoiceSpec;
  1151. typedef struct VoiceDescription {
  1152.     long                length;                    // size of structure - set by application 
  1153.     VoiceSpec                voice;                    // voice creator and ID info 
  1154.     long                version;                    // version code for voice 
  1155.     Str63                name;                    // name of voice 
  1156.     Str255                comment;                    // additional text info about voice 
  1157.     short                gender;                    // neuter, male, or female 
  1158.     short                age;                    // approximate age in years 
  1159.     short                script;                    // script code of text voice can process 
  1160.     short                language;                    // language code of voice output 
  1161.     short                region;                    // region code of voice output 
  1162.     long                reserved[4];                    // reserved for future use 
  1163. } VoiceDescription;
  1164.  
  1165. typedef struct VoiceFileInfo {
  1166.     FSSpec            fileSpec;                // volume, dir, & name information for voice file 
  1167.     short            resID;                // resource ID of voice in the file 
  1168. } VoiceFileInfo;
  1169. typedef struct SpeechStatusInfo {
  1170.     Boolean            outputBusy;                        // true if audio is playing 
  1171.     Boolean            outputPaused;                        // true if channel is paused 
  1172.     long            inputBytesLeft;                        // bytes left to process 
  1173.     short            phonemeCode;                        // opcode for cur phoneme 
  1174. } SpeechStatusInfo;
  1175.  
  1176. typedef struct SpeechErrorInfo {
  1177.     short            count;            // # of errs since last check 
  1178.     OSErr            oldest;            // oldest unread error 
  1179.     long            oldPos;            // char position of oldest err 
  1180.     OSErr            newest;            // most recent error 
  1181.     long            newPos;            // char position of newest err 
  1182. } SpeechErrorInfo;
  1183.  
  1184. typedef struct SpeechVersionInfo {
  1185.     OSType                synthType;                            // always 'ttsc' 
  1186.     OSType                synthSubType;                            // synth flavor 
  1187.     OSType                synthManufacturer;                            // synth creator ID 
  1188.     long                synthFlags;                            // synth feature flags 
  1189.     NumVersion                synthVersion;                            // synth version number 
  1190. } SpeechVersionInfo;
  1191. typedef struct PhonemeInfo {
  1192.     short            opcode;                    // opcode for the phoneme 
  1193.     Str15            phStr;                    // corresponding char string 
  1194.     Str31            exampleStr;                    // word that shows use of phoneme 
  1195.     short            hiliteStart;                    // segment of example word that 
  1196.     short            hiliteEnd;                    //   hilighted text (ala TextEdit) 
  1197. } PhonemeInfo;
  1198.  
  1199. typedef struct PhonemeDescriptor {
  1200.     short                    phonemeCount;                        // # of elements 
  1201.     PhonemeInfo                    thePhonemes[1];                        // element list 
  1202. } PhonemeDescriptor;
  1203.  
  1204. typedef struct SpeechXtndData {
  1205.     OSType            synthCreator;                    // synth creator ID 
  1206.     Byte            synthData[2];                    // data TBD by synth 
  1207. } SpeechXtndData;
  1208. typedef struct DelimiterInfo {
  1209.     Byte            startDelimiter[2];                            // defaults to [[ 
  1210.     Byte            endDelimiter[2];                            // defaults to ]] 
  1211. } DelimiterInfo;
  1212. Voice Routines
  1213.  
  1214. pascal OSErr MakeVoiceSpec (OSType creator, OSType id, VoiceSpec *voice);
  1215. pascal OSErr CountVoices (short *numVoices);
  1216. pascal OSErr GetIndVoice (short index, VoiceSpec *voice);
  1217. pascal OSErr GetVoiceDescription (VoiceSpec *voice, VoiceDescription *info,
  1218.      long infoLength);
  1219. pascal OSErr GetVoiceInfo (VoiceSpec *voice, OSType selector, void
  1220.      *voiceInfo);
  1221. Routines for Managing Speech Channels
  1222.  
  1223. pascal OSErr NewSpeechChannel (VoiceSpec *voice, SpeechChannel *chan);
  1224. pascal OSErr DisposeSpeechChannel (SpeechChannel chan);
  1225. Speaking Routines
  1226.  
  1227. pascal OSErr SpeakString (StringPtr s);
  1228. pascal OSErr SpeakText (SpeechChannel chan, Ptr textBuf, long textBytes);
  1229. pascal OSErr StopSpeech (SpeechChannel chan);
  1230. pascal OSErr StopSpeechAt (SpeechChannel chan, long whereToStop);
  1231. pascal OSErr PauseSpeechAt (SpeechChannel chan, long whereToPause);
  1232. pascal OSErr ContinueSpeech (SpeechChannel chan);
  1233. pascal OSErr SpeakBuffer (SpeechChannel chan, Ptr textBuf, long textBytes,
  1234.     long controlFlags);
  1235. Information and Control Routines
  1236.  
  1237. pascal NumVersion SpeechManagerVersion (void);
  1238. pascal short SpeechBusy (void);
  1239. pascal OSErr SetSpeechRate (SpeechChannel chan, Fixed rate);
  1240. pascal OSErr GetSpeechRate (SpeechChannel chan, Fixed *rate);
  1241. pascal OSErr SetSpeechPitch (SpeechChannel chan, Fixed pitch);
  1242. pascal OSErr GetSpeechPitch (SpeechChannel chan, Fixed *pitch);
  1243. pascal short SpeechBusySystemWide (void);
  1244. pascal OSErr SetSpeechInfo (SpeechChannel chan, OSType selector, void
  1245.      *speechInfo);
  1246. pascal OSErr GetSpeechInfo (SpeechChannel chan, OSType selector, void
  1247.      *speechInfo);
  1248. Text-to-Phoneme Conversion Routine
  1249.  
  1250. pascal OSErr TextToPhonemes (SpeechChannel chan, Ptr textBuf, 
  1251.     long textBytes, Handle phonemeBuf, long *phonemeBytes) 
  1252. Dictionary Management Routine
  1253.  
  1254. pascal OSErr UseDictionary (SpeechChannel chan, Handle dictionary)
  1255. Callback Prototypes
  1256.  
  1257.         // text-done callback routine typedef 
  1258. typedef pascal void (*TextDoneProcPtr) (SpeechChannel, long, Ptr *, long *,
  1259.          long *);
  1260.  
  1261.         // speech-done callback routine typedef 
  1262. typedef pascal void (*SpeechDoneProcPtr) (SpeechChannel, long );
  1263.  
  1264.         // sync callback routine typedef 
  1265. typedef pascal void (*SyncProcPtr) (SpeechChannel, long, OSType);
  1266.  
  1267.         // error callback routine typedef 
  1268. typedef pascal void (*ErrorProcPtr) (SpeechChannel, long, OSErr, long);
  1269.  
  1270.         // phoneme callback routine typedef 
  1271. typedef pascal void (*PhonemeProcPtr) (SpeechChannel, long, short);
  1272.  
  1273.         // word callback routine typedef 
  1274. typedef pascal void (*WordProcPtr) (SpeechChannel, long, long, short);
  1275. Error Return CodesnoErr    0    No error    
  1276. paramErr    –50    Parameter error    
  1277. memFullErr    –108    Not enough memory to speak    
  1278. nilHandleErr    –109    Handle argument is nil    
  1279. siUnknownInfoType    –231    Feature not implemented on synthesizer    
  1280. noSynthFound    –240    Could not find the specified speech synthesizer    
  1281. synthOpenFailed    –241    Could not open another speech synthesizer channel    
  1282. synthNotReady    –242    Speech synthesizer is still busy speaking    
  1283. bufTooSmall    –243    Output buffer is too small to hold result    
  1284. voiceNotFound    –244    Voice resource not found    
  1285. incompatibleVoice    –245    Specified voice cannot be used with synthesizer    
  1286. badDictFormat    –246    Format problem with pronunciation dictionary    
  1287. badPhonemeText    –247    Raw phoneme text contains invalid characters    
  1288. invalidComponentID    –3000    Invalid SpeechChannel parameter    
  1289.  
  1290.  
  1291.  
  1292.